import tkinter as tk
from tkinter import scrolledtext, messagebox
import subprocess
import threading
import os
import sys


class App:
    def __init__(self, root):
        self.root = root
        self.root.title("定时任务与绘图控制面板")
        self.root.geometry("800x600")

        # 当前脚本所在目录
        self.script_dir = os.path.dirname(os.path.abspath(__file__))

        # 终端输出区域
        self.output_text = scrolledtext.ScrolledText(root, wrap=tk.WORD, height=20)
        self.output_text.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

        # 按钮框架
        button_frame = tk.Frame(root)
        button_frame.pack(pady=10)

        # 开始按钮
        self.start_button = tk.Button(button_frame, text="开始定时任务", width=15,
                                      command=lambda: self.start_script("time"))
        self.start_button.grid(row=0, column=0, padx=5)

        # 停止按钮
        self.stop_button = tk.Button(button_frame, text="停止定时任务", width=15,
                                     command=lambda: self.stop_script("time"))
        self.stop_button.grid(row=0, column=1, padx=5)

        # 绘图按钮
        self.plot_button = tk.Button(button_frame, text="运行绘图", width=15,
                                     command=lambda: self.run_script("view"))
        self.plot_button.grid(row=0, column=2, padx=5)

        # 启动 Superset 按钮
        self.superset_button = tk.Button(button_frame, text="启动Superset", width=15,
                                         command=lambda: self.start_script("superset"))
        self.superset_button.grid(row=0, column=3, padx=5)

        # 停止 Superset 按钮
        self.stop_superset_button = tk.Button(button_frame, text="停止Superset", width=15,
                                              command=lambda: self.stop_script("superset"))
        self.stop_superset_button.grid(row=0, column=4, padx=5)

        # 子进程管理器 {script_name: process}
        self.processes = {}

    def _redirect_output(self, process, name):
        """将子进程的标准输出写入到 Text 控件"""
        for line in iter(process.stdout.readline, ''):
            self.output_text.insert(tk.END, f"[{name}] {line}")
            self.output_text.see(tk.END)
        process.stdout.close()

    def start_script(self, script_name):
        script_map = {
            "time": "time.py",
            "superset": "superset.py"
        }

        if script_name not in script_map:
            self.output_text.insert(tk.END, f"未知脚本名: {script_name}\n")
            return

        full_path = os.path.join(self.script_dir, script_map[script_name])

        if script_name in self.processes:
            proc = self.processes[script_name]
            if proc.poll() is None:
                self.output_text.insert(tk.END, f"{script_name} 脚本已在运行中...\n")
                return

        self.output_text.insert(tk.END, f"正在启动脚本: {full_path}\n")

        creationflags = 0
        if os.name == 'nt':
            creationflags = subprocess.CREATE_NEW_PROCESS_GROUP

        process = subprocess.Popen(
            [sys.executable, full_path],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            stdin=subprocess.PIPE,
            universal_newlines=True,
            creationflags=creationflags
        )

        self.processes[script_name] = process

        # 独立线程读取输出
        thread = threading.Thread(target=self._redirect_output, args=(process, script_name))
        thread.daemon = True
        thread.start()

    def stop_script(self, script_name):
        if script_name not in self.processes:
            self.output_text.insert(tk.END, f"{script_name} 进程未启动。\n")
            return

        process = self.processes[script_name]

        if process.poll() is None:
            self.output_text.insert(tk.END, f"发送终止信号给 {script_name} ...\n")
            try:
                if os.name == 'nt':
                    import signal
                    process.send_signal(signal.CTRL_BREAK_EVENT)
                else:
                    process.terminate()
                process.wait(timeout=3)
            except subprocess.TimeoutExpired:
                self.output_text.insert(tk.END, f"{script_name} 进程超时，强制结束...\n")
                process.kill()
            finally:
                self.processes.pop(script_name, None)
                self.output_text.insert(tk.END, f"{script_name} 脚本已终止。\n")
        else:
            self.output_text.insert(tk.END, f"{script_name} 脚本已经停止。\n")

    def run_script(self, script_name):
        script_map = {
            "view": "view.py"
        }

        if script_name not in script_map:
            self.output_text.insert(tk.END, f"未知脚本名: {script_name}\n")
            return

        full_path = os.path.join(self.script_dir, script_map[script_name])
        self.output_text.insert(tk.END, f"运行脚本: {full_path}\n")

        try:
            result = subprocess.run([sys.executable, full_path], check=True)
            self.output_text.insert(tk.END, f"{script_name} 脚本执行完成。\n")
        except subprocess.CalledProcessError as e:
            self.output_text.insert(tk.END, f"{script_name} 脚本执行失败，错误代码: {e.returncode}\n")

    def on_closing(self):
        """窗口关闭时自动终止所有子进程"""
        running = [k for k, v in self.processes.items() if v.poll() is None]
        if running:
            confirm = messagebox.askokcancel("确认退出", "有脚本正在运行，确定要退出吗？")
            if not confirm:
                return
            for name in running:
                self.stop_script(name)
        self.root.destroy()


if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)

    # 绑定窗口关闭事件
    root.protocol("WM_DELETE_WINDOW", app.on_closing)

    root.mainloop()